﻿using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Xml.Linq;
using Avivo.Common;

namespace Avivo.Tools.Sprite
{
	//TODO: Optimize by combining xaml panels then render to raster once
	public class Program
	{
		public static ILogger Logger;

		#region Entry point
		[STAThreadAttribute()]
		static void Main(string[] arguments)
		{
			//Initialize logger
			Logger = new ConsoleLogger();
			Converter.Logger = Logger;
			SpriteRenderEngine.Logger = Logger;

			//Sample
			//arguments = new string[]
			//{
			//  @"--verbose",
			//  @"--input-xml=""d0c502d8e7d6d19ea436de67dd2ee289-button.in.xml""",
			//  @"--output-xml=""d0c502d8e7d6d19ea436de67dd2ee289-button.out.xml""",
			//  @"--output-image=""d0c502d8e7d6d19ea436de67dd2ee289-button.png""",
			//};

			try
			{
				//Parse command line arguments
				Arguments args = new Arguments(arguments);

				if (args != null && args.Count > 0)
				{
					//Flags
					Settings.Verbose = args.Contains("v") || args.Contains("verbose");

					if (args.Contains("help"))
					{
						Console.WriteLine(Settings.HelpMessage);
						return;
					}

					if (args.Contains("debug"))
					{
						//Console.WriteLine(Settings.AppBasePath);
						foreach (DictionaryEntry arg in args)
						{
							Console.WriteLine(arg.Key + " = " + arg.Value);
						}
						return;
					}

					//Input xml
					if (args.Contains("input-xml") && args.Contains("output-xml")  && args.Contains("output-image"))
					{
						//Start the updating process
						string xml = File.ReadAllText(args["input-xml"]);
						SpriteGrid grid = SpriteGrid.Create(XDocument.Parse(xml));
						if (SpriteRenderEngine.RenderSprite(ref grid, args["output-image"]))
						{
							XDocument doc = new XDocument();
							doc.Add(grid.ToXElement());
							doc.Save(args["output-xml"]);
						}
					}
					else
					{
						Console.WriteLine(Settings.SyntaxError);
					}
				}
				else
				{
					Console.WriteLine(Settings.HelpMessage);
				}
			}
			catch (Exception ex)
			{
				Logger.WriteLine(ex.Message);
				Logger.WriteLine(ex.StackTrace);
			}
		}
		#endregion

		public static bool GenerateSprite(ref SpriteGrid grid, string imagePath)
		{
			//Create target directory
			string targetDirectory = Path.GetDirectoryName(imagePath);
			if (!Directory.Exists(targetDirectory))
			{
				Directory.CreateDirectory(targetDirectory);
			}

			//Create a xml file
			string inputXmlPath = Path.ChangeExtension(imagePath, ".in.xml");
			string outputXmlPath = Path.ChangeExtension(imagePath, ".out.xml");
			XDocument doc = new XDocument();
			doc.Add(grid.ToXElement());
			doc.Save(inputXmlPath);

			string bin = null; //TODO: Find a better way to get the 'bin' path
			bin = AppDomain.CurrentDomain.BaseDirectory + "bin\\" + Settings.Name + ".exe";
			if (!File.Exists(bin))
			{
				bin = AppDomain.CurrentDomain.BaseDirectory + Settings.Name + ".exe";
			}

			//Execute xaml converter
			Process process = new Process();
			process.StartInfo.FileName = bin;
			process.StartInfo.Arguments = string.Format("--verbose --input-xml=\"{0}\" --output-xml=\"{1}\" --output-image=\"{2}\"", inputXmlPath, outputXmlPath, imagePath);
			process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

#if DEBUG
			process.StartInfo.UseShellExecute = false;
			process.StartInfo.RedirectStandardOutput = true;
			process.Start();
			string output = process.StandardOutput.ReadToEnd();
#else
      process.Start();
#endif

			//NOTE: Process must close completely to avoid the locked Session problem described Ticket #2: "Session expires when running external process (application)"
			//Session: http://nicholas.piasecki.name/blog/2009/02/on-web-gardens-aspnet-and-iis-60/

			//Wait while process is running
			process.WaitForExit();
			process.Dispose();

			string xml = File.ReadAllText(outputXmlPath);
			doc = XDocument.Parse(xml);
			grid = SpriteGrid.Create(doc);

			File.Delete(inputXmlPath);
			File.Delete(outputXmlPath);
			return (grid != null);
		}

		public static bool GenerateSpriteWithoutExternalProcess(ref SpriteGrid grid, string imagePath)
		{
			return SpriteRenderEngine.RenderSprite(ref grid, imagePath);
		}
	}
}
